package com.pap.upload.file.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.pap.base.controller.BaseController;
import com.pap.base.util.date.DateUtils;
import com.pap.base.util.string.StringUtilss;
import com.pap.upload.agent.file.IBaseFileAgent;
import com.pap.upload.file.auto.entity.BaseFile;
import com.pap.upload.file.exception.FileException;
import com.pap.upload.file.util.ZipUtil;

@RestController
@RequestMapping("/v1/file")
@PropertySource({ "classpath:static/upload.properties" })
public class BaseFileController extends BaseController<BaseFile, IBaseFileAgent> {

	private static Logger logger = LoggerFactory.getLogger(BaseFileController.class);

	@Resource(name = "baseFileAgent")
	@Override
	public void setService(IBaseFileAgent agent) {
		super.service = agent;
	}

	// 文件上传路径
	@Value("${pap.sp.upload.root}")
	private String path;

	/**
	 * 功能： <br/>
	 *
	 */
	@RequestMapping("/download")
	public void download(String id, String name, HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		BaseFile baseFile = service.selectByPrimaryKey(id);

		File file = new File(baseFile.getFilePath());

		// 下载文件名
		// 针对IE或者以IE为内核的浏览器：
		String userAgent = request.getHeader("User-Agent");
		if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
			name = java.net.URLEncoder.encode(name, "UTF-8");
		} else {
			// 非IE浏览器的处理：
			name = new String(name.getBytes("UTF-8"), "ISO-8859-1");
		}
		
		String suffix = "";
		int index = baseFile.getFilePath().lastIndexOf('.');
		if (index != -1) {
			suffix = baseFile.getFilePath().substring(index + 1);
		}
		
		response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", name + "." + suffix));

		// 下载
		try {
			ServletOutputStream out;
			FileInputStream inputStream = new FileInputStream(file);

			// 3.通过response获取ServletOutputStream对象(out)
			out = response.getOutputStream();

			int b = 0;
			byte[] buffer = new byte[512];
			while (b != -1) {
				b = inputStream.read(buffer);
				// 4.写到输出流(out)中
				out.write(buffer, 0, b);
			}
			inputStream.close();
			out.close();
			out.flush();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 功能：批量下载，将多个文件打包为zip后下载 <br/>
	 *
	 */
	@RequestMapping(value = "/download/zip", method = { RequestMethod.POST, RequestMethod.GET })
	public void downloadZip(String info, String name, Boolean decode, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		if (Boolean.TRUE.equals(decode)) {
			info = URLDecoder.decode(info, "UTF-8");
			if (!StringUtilss.isEmpty(name)) {
				name = URLDecoder.decode(name, "UTF-8");
			}

			logger.debug("the decoded info is : {}", info);
			logger.debug("the decoded name is : {}", name);
		}

		Map<File, String> files = new LinkedHashMap<>();
		// id:name;id:name;
		for (String part : info.split(";")) {

			String id = part;
			
			BaseFile baseFile = service.selectByPrimaryKey(id);

			File file = new File(baseFile.getFilePath());
			if (!file.exists()) {
				// 文件不存在
				throw new FileException("download.file.not.exist", new Object[] { id });
			}

			String suffix = "";
			int index = baseFile.getFilePath().lastIndexOf('.');
			if (index != -1) {
				suffix = baseFile.getFilePath().substring(index + 1);
			}
			// 放入容器   带文件后缀
			files.put(file, baseFile.getName() + "." + suffix);
		}

		// 生成zip文件
		File zipFile = new File(new File(path), UUID.randomUUID().toString());
		ZipUtil.generatorZipFile(files, zipFile);

		// 下载文件名
		// 针对IE或者以IE为内核的浏览器：
		String userAgent = request.getHeader("User-Agent");
		if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
			name = java.net.URLEncoder.encode(name, "UTF-8");
		} else {
			// 非IE浏览器的处理：
			name = new String(name.getBytes("UTF-8"), "ISO-8859-1");
		}
		response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", name + ".zip"));

		// 下载
		try {
			ServletOutputStream out;
			FileInputStream inputStream = new FileInputStream(zipFile);

			// 3.通过response获取ServletOutputStream对象(out)
			out = response.getOutputStream();

			int b = 0;
			byte[] buffer = new byte[512];
			while (b != -1) {
				b = inputStream.read(buffer);
				// 4.写到输出流(out)中
				out.write(buffer, 0, b);
			}
			inputStream.close();
			out.close();
			out.flush();

		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 功能：批量上传 <br/>
	 *
	 */
	@ResponseBody
	@RequestMapping(value = "/uploadbatch", method = RequestMethod.POST)
	public List<String> uploadBatch(String orderId, String contId, String name, String fileType,
			String fileCustomerType, @RequestParam("file") MultipartFile[] files,
			@RequestHeader(value = "clientLicenseId", defaultValue = "-1") String clientLicenseId,
			@RequestHeader(value = "loginUserId", defaultValue = "-1") String loginUserId) throws Exception {
		List<String> urls = new ArrayList<>(files.length);

		for (MultipartFile file : files) {
			urls.add(save(orderId, contId, name, fileType, fileCustomerType, clientLicenseId, loginUserId, file));
		}

		return urls;
	}

	/**
	 * 功能：文件上传 <br/>
	 *
	 */
	@ResponseBody
	@RequestMapping(value = "/upload", method = RequestMethod.POST)
	public Map<String, Object> upload(String orderId, String contId, String name, String fileType,
			String fileCustomerType, MultipartFile file,
			@RequestHeader(value = "clientLicenseId", defaultValue = "-1") String clientLicenseId,
			@RequestHeader(value = "loginUserId", defaultValue = "-1") String loginUserId) throws Exception {
		Map<String, Object> map = new LinkedHashMap<String, Object>();
		String fileId = save(orderId, contId, name, fileType, fileCustomerType, clientLicenseId, loginUserId, file);
		
		// 文件id
		map.put("id", fileId);
		return map;
	}

	private String save(String orderId, String contId, String name, String fileType,
			String fileCustomerType, String clientLicenseId, String loginUserId, MultipartFile file) throws Exception {
		String idStr = UUID.randomUUID().toString();
		String nameOriginal = file.getOriginalFilename();
		String suffix = "";
		int index = nameOriginal.lastIndexOf('.');
		if (index != -1) {
			suffix = nameOriginal.substring(index + 1);
		}

		File target = new File(new File(path),
				UUID.randomUUID().toString() + "." + suffix);

		// 创建父类文件夹
		File parentTarget = target.getParentFile();
		if (!parentTarget.exists()) {
			parentTarget.mkdirs();
		}

		try {
			// 将接收的文件保存到指定文件中
			file.transferTo(target);
			
			// 保存至数据库
			BaseFile baseFileEntity = new BaseFile();
			baseFileEntity.setId(idStr);
			baseFileEntity.setOrderId(orderId);
			baseFileEntity.setContId(contId);
			baseFileEntity.setName(name);
			baseFileEntity.setFileType(fileType);
			baseFileEntity.setFileCustomerType(fileCustomerType);
			baseFileEntity.setFilePath(target.getPath());
			baseFileEntity.setCreateIp("0.0.0.0");
			baseFileEntity.setCreateTime(DateUtils.getCurrDateTimeStr());
			baseFileEntity.setCreateUser(loginUserId);
			baseFileEntity.setClientLicenseId(clientLicenseId);
			service.insertSelective(baseFileEntity);
			
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// 文件id
		return idStr;
	}

}
